package controllers

import (
	"errors"
	"fmt"
	"goblog/app/models/user"
	"goblog/app/requests"
	"goblog/pkg/auth"
	"goblog/pkg/flash"
	"goblog/pkg/logger"
	"goblog/pkg/route"
	"goblog/pkg/view"
	"gorm.io/gorm"
	"net/http"
	"strconv"
)

type AuthController struct {
}

// Register 注册表单
func (*AuthController) Register(w http.ResponseWriter, r *http.Request) {
	view.RenderSimple(w, view.D{}, "auth.register")
}

// DoRegister 处理注册逻辑
func (*AuthController) DoRegister(w http.ResponseWriter, r *http.Request) {
	// 1. 初始化数据
	_user := user.User{
		Name:            r.PostFormValue("name"),
		Email:           r.PostFormValue("email"),
		Password:        r.PostFormValue("password"),
		PasswordConfirm: r.PostFormValue("password_confirm"),
	}

	// 2. 开始验证
	errs := requests.ValidateRegistrationForm(_user)

	if len(errs) > 0 {
		// 4.1 有错误发生，打印数据
		view.RenderSimple(w, view.D{
			"Errors": errs,
			"User":   _user,
		}, "auth.register")
	} else {

		_ = _user.Create()
		if _user.Id > 0 {
			// 登录
			flash.Success("恭喜您注册成功！")
			auth.Login(_user)
			http.Redirect(w, r, "/", http.StatusFound) // 302 重定向
		} else {
			w.WriteHeader(http.StatusInternalServerError)
			_, _ = fmt.Fprint(w, "注册失败，请联系管理员~")
		}
	}
}

// Login 登录
func (*AuthController) Login(w http.ResponseWriter, r *http.Request) {

	// 测试 新增会话数据
	//session.Put("uid", 1)
	//fmt.Fprint(w, session.Get("uid"))
	//session.Forget("uid")
	//session.Flush()

	view.RenderSimple(w, view.D{}, "auth.login")
}

// DoLogin 处理登录逻辑
func (*AuthController) DoLogin(w http.ResponseWriter, r *http.Request) {
	// 1. 初始化数据
	email := r.PostFormValue("email")
	password := r.PostFormValue("password")

	if err := auth.Attempt(email, password); err == nil {
		// 登录成功
		flash.Success("欢迎回来！")
		http.Redirect(w, r, "/", http.StatusFound) // 302 重定向
	} else {
		view.RenderSimple(w, view.D{
			"Error":    err.Error(),
			"Email":    email,
			"Password": password,
		}, "auth.login")
	}
}

// Logout 退出登录
func (*AuthController) Logout(w http.ResponseWriter, r *http.Request) {
	auth.Logout()
	flash.Success("您已退出登录~")
	http.Redirect(w, r, "/", http.StatusFound) // 302 重定向
}

func (*AuthController) SendEmail(w http.ResponseWriter, r *http.Request) {
	view.RenderSimple(w, view.D{}, "auth.sendemail")
}

func (*AuthController) DoSendEmail(w http.ResponseWriter, r *http.Request) {

	email := r.PostFormValue("email")
	_user, err := user.GetByEmail(email)

	var e error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			e = errors.New("账号不存在，请先注册")
		} else {
			e = errors.New("内部错误，请稍后重试~")
		}
		view.RenderSimple(w, view.D{
			"Error": e.Error(),
			"Email": email,
		}, "auth.sendemail")
	} else {
		id := _user.Id
		// TODO 发送带验证链接邮件

		flash.Success("邮件发送成，ID："+strconv.FormatUint(id, 10))
		http.Redirect(w, r, "/", http.StatusFound) // 302 重定向
	}
}

// ResetPassword 重置密码表单
func (*AuthController) ResetPassword(w http.ResponseWriter, r *http.Request) {
	id := route.GetRouteVariable("id", r)
	view.RenderSimple(w, view.D{
		"ID": id,
	}, "auth.reset")
}

// DoResetPassword 重置密码
func (*AuthController) DoResetPassword(w http.ResponseWriter, r *http.Request) {
	id := r.PostFormValue("id")
	_user, err := user.Get(id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			w.WriteHeader(http.StatusNotFound)
			_, _ = fmt.Fprint(w, "404 用户未找到")
		} else {
			logger.LogError(err)
			w.WriteHeader(http.StatusInternalServerError)
			_, _ = fmt.Fprint(w, "500 服务器内部错误")
		}
	} else {
		// 1. 初始化数据
		pwd := user.User{
			Name:            r.PostFormValue("name"),
			Email:           r.PostFormValue("email"),
			Password:        r.PostFormValue("password"),
			PasswordConfirm: r.PostFormValue("password_confirm"),
		}

		// 2. 开始验证
		errs := requests.ValidateResetPasswordForm(pwd)

		if len(errs) > 0 {
			// 4.1 有错误发生，打印数据
			view.RenderSimple(w, view.D{
				"Errors": errs,
				"User":   pwd,
				"ID":     id,
			}, "auth.reset")
		} else {
			_user.Password = _user.Password
			rowsAffected, err := _user.Update()
			if err != nil {
				// 数据库错误
				w.WriteHeader(http.StatusInternalServerError)
				_, _ = fmt.Fprint(w, "500 服务器内部错误")
				return
			}
			if rowsAffected > 0 {
				showURL := route.Name2URL("auth.login")
				http.Redirect(w, r, showURL, http.StatusFound)
			} else {
				_, _ = fmt.Fprint(w, "您没有做任何更改！")
			}
		}
	}
}
